#include "TcpServer.hpp"
#include <memory>

using namespace tcpserver;

static void Usage(std::string proc)
{
    std::cerr << "Usage:\n\t" << proc << " port" << "\n\n";
}

bool cal(const Request &req, Response &resp)
{
    // req有结构化完成的数据，可以直接使用
    resp.exitcode = OK;
    resp.result = OK;

    switch (req.op)
    {
    case '+':
        resp.result = req.x + req.y;
        break;
    case '-':
        resp.result = req.x - req.y;
        break;
    case '*':
        resp.result = req.x * req.y;
        break;
    case '/':
    {
        if (req.y == 0)
            resp.exitcode = DIV_ZERO;
        else
            resp.result = req.x / req.y;
    }
    break;
    case '%':
    {
        if (req.y == 0)
            resp.exitcode = MOD_ZERO;
        else
            resp.result = req.x % req.y;
    }
    break;
    default:
        resp.exitcode = OP_ERROR;
        break;
    }

    return true;
}

void calculate(Connection *conn)
{
    std::string onePackage;
    while (ParseOnePackage(conn->_inbuffer, &onePackage))
    {
        // 1. 去报头
        std::string reqStr;
        if (!deLength(onePackage, &reqStr))
            return;
        std::cout << "去报头的正文：\n " << reqStr << std::endl;

        // 2. 反序列化
        Request req;
        if (!req.deserialize(reqStr))
            return;

        // 3. 计算处理
        Response resp;
        cal(req, resp);

        // 4. 构建响应
        std::string respStr;
        resp.serialize(&respStr);

        // 5. 添加报头
        conn->_outbuffer += enLength(respStr);
    }
    // 6. 发送数据
    if (conn->_sender)
        conn->_sender(conn);
    // 如果没有发完，需要对对应的sock开启写事件关心，如果发完了，就要关闭
    // if (!conn->_outbuffer.empty())
    // {
    //     conn->_tsp->EnableReadWrite(conn, true, true);
    // }
    // else
    //     conn->_tsp->EnableReadWrite(conn, true, false);
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage(argv[0]);
        exit(USAGE_ERR);
    }
    uint16_t port = atoi(argv[1]);

    std::unique_ptr<TcpServer> tsvr(new TcpServer(calculate, port));

    tsvr->InitServer();

    tsvr->Dispatch();

    return 0;
}